/*****************************************************************************
 * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Macros (excluding function macros).
 *//*
 * LEGAL:   COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#ifndef DOXYGEN  // doxygen can't parse this correctly
#ifndef BASE_MACROS_HH
#define BASE_MACROS_HH 1

namespace base {

////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////  macros  /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/*******************************************************************************
 * Instead of writing "static" which raises concerns about thread-safety.
 *******************************************************************************/
#define PERSISTENT   static
#define INLINE       static inline
#ifndef INTERN                  // tests can predefine to test static functions
#define INTERN       static
#endif
#ifndef INTERNAL
#define INTERNAL     static
#endif
#define CLASS_CONST  static const
#define CLASS_VAR    static
#define CLASS_METHOD static

/*******************************************************************************
 * Prevent copying an object.  Put these in the private section of a class.
 * The copy methods are prototypes without definitions, so usage causes a linker error.
 *******************************************************************************/
#define PREVENT_COPYING( CLASS )        \
private:                                \
    CLASS( const CLASS& );              \
    CLASS& operator=( const CLASS& );

/*******************************************************************************
 * To mark classes that are copyable.  Antonym of PREVENT_COPYING().
 *******************************************************************************/
#define COPYABLE( CLASS )

/*******************************************************************************
 * Put this in destructors of globals which may call other globals
 * to avoid pitfall of undefined order of destruction.
 *******************************************************************************/
#define RETURN_IF_EXITING  {{ if ( base::gGlobals.mExiting ) return; }}

/*******************************************************************************
 * Arcane indirect trick to give a variable a unique name.
 * Subtlety: If written on the same line, UNIQUE_NAME() expands the same name.
 * That's a feature not a bug.  BEGIN_ONCE depends on it.
 *******************************************************************************/
#define UNIQUE_NAME__(NAME,LINE) NAME##LINE
#define UNIQUE_NAME_(NAME,LINE)  UNIQUE_NAME__(NAME,LINE)
#define UNIQUE_NAME(NAME)        UNIQUE_NAME_(NAME,__LINE__)

/*******************************************************************************
 * @def BEGIN_ONCE
 * BEGIN_ONCE {  <-- write brace
 * ...
 * } END_ONCE
 * Subtlety: This must be one-line because of UNIQUE_NAME().
 *******************************************************************************/
#define BEGIN_ONCE                          \
{                                           \
    PERSISTENT int UNIQUE_NAME(once);       \
    ++UNIQUE_NAME(once);                    \
    if ( UNIQUE_NAME(once) == 1 )

#define END_ONCE \
}

/*******************************************************************************
 * @def likely
 * Branch hint for compiler.
 *******************************************************************************/
#if __GNUC__ >= 3
#define EX(COND)  __builtin_expect((COND),1)  ///< expected condition
#define UX(COND)  __builtin_expect((COND),0)  ///< unexpected condition
#else
#define EX(COND) (COND)
#define UX(COND) (COND)
#endif

/*******************************************************************************
 * @def UNUSED
 * Tell compiler a var is unused.
 *******************************************************************************/
#if GCC_VERSION >= 30100  // if gcc-3.1 or later
#define UNUSED    __attribute__ ((unused))
#define DEBUG_VAR __attribute__ ((unused))
#define NO_INLINE  __attribute__ ((noinline))
#else
#define UNUSED
#define DEBUG_VAR
#define NO_INLINE
#endif

} // namespace base

#endif // BASE_MACROS_HH
#endif // DOXYGEN
